#include<iostream>
#include<string>
#include <unistd.h>
#include<vector>
#include <sys/wait.h>
#include"Task.hpp"
using namespace std;
class Channel 
{
public:
    Channel(int wfd,pid_t subprocessid, const ::string &name):
    _wfd(wfd),_subprocessid(subprocessid),_name(name)
    {


    }
    int GetWfd(){return _wfd;}
    pid_t GetProcessId(){return _subprocessid;}
    std::string GetName(){return _name;} 
    ~Channel()
    {

    }
    void CloseChannel()
    {
        close(_wfd);
    }
    void Wait()
    {
        pid_t rid=waitpid(_subprocessid,nullptr,0);
        if(rid>0)
        {
            cout<<"wait"<<rid<<"success"<<endl;
        }

    }
    

private:
    int _wfd;//这里是写管道进程的fid
    pid_t _subprocessid;//子进程id
    std::string  _name;//管道的名字
};
void work(int rfd)
{
     while(true)
     {
        int command=0;
        int n=read(rfd,&command,sizeof(command));
        if(n==sizeof(int))//read成功
        {
            cout<<"pid is:"<<getpid()<<"headler task"<<endl;
            ExcuteTask(command);
        }
        else if (n == 0)
        {
            std::cout << "sub process : " << getpid() << " quit" << std::endl;
            break;
        }
     }
}
void CreatChannelAndSub(vector<Channel>*channels,int num)
{
    //BUG
     for(int i=0;i<num;i++)//创建进程创建管道和管理管道数组的填充
    {
        int pipefd[2]={0};//管道的连进程的fid
        int n=pipe(pipefd);//1.创建管道
        if(n<0) exit(1);
        pid_t id=fork();
        if(id==0)
        {
            //child    //2.创建进程
            close(pipefd[1]);
            work(pipefd[0]);
            exit(0);

        }
        //构造管道名字
        std::string channel_name ="Channel-"+std::to_string(i);
        //父进程
        close(pipefd[0]);
        //父进程有的东西
        //a.子进程的pid
        //b.该循环的管道的写端
        channels->push_back(Channel(pipefd[1],id,channel_name));


    }

}
int  NextChannel(int channelnumber)
{
    static int next=0;
    int channel=next;
    next++;
    next%=channelnumber;
    return channel;
}
void SendTaskCommand( Channel & channel, int taskcommand)// SendTaskCommand(const Channel&channel, int taskcommand)这里错误的原因是const对象的函数一定义要是const的
{
    write(channel.GetWfd(),&taskcommand,sizeof(taskcommand));

}
void ctrlProcessOnce(vector<Channel>&channels)
{
     sleep(1);
         //a.选择一个任务
        int taskcommand=SelectTask();
        //b.选择一个进程和星岛
        int channel_index=NextChannel(channels.size());
        //c.发送
        SendTaskCommand(channels[channel_index],taskcommand);
        std::cout << std::endl;
        std::cout << "taskcommand: " << taskcommand << " channel: "
          << channels[channel_index].GetName() << " sub process: " << channels[channel_index].GetProcessId() << std::endl;
}
void ctrlProcess(vector<Channel>&channels,int times=-1)
{
    if(times>0)
    {
        while(times--)
        {
            ctrlProcessOnce(channels);
        }
    }
    else
    {
        while(true)
        {
            ctrlProcessOnce(channels);
        }

    }
}
void CleanUpChannel(vector<Channel>&channels)
{
    for(auto &channel:channels)
    {
        channel.CloseChannel();
       
    }
    for(auto &channel:channels)
    {
         channel.Wait();
    }
}
//使用子进程的命令行表示：./processpool 5
int main(int argc,char *const argv[])//main的参数 
{
    if(argc != 2)//一个是pr 另一个是5
    {
        std::cerr<<"Usage"<<argv[0]<<"processnum"<<std::endl;
        exit(1);
    }
    int num=std::stoi(argv[1]);//管道个数
    InitTask();//父进程建立任务表；
    std ::vector<Channel> channels;
   //1.创建行道和进程和准备管理管道数组
    CreatChannelAndSub(&channels,num);
    // for(auto &channel :channels)
    // {
    //   cout<<"================================"<<endl;
    //   cout<<channel.GetWfd()<<endl;
    //   cout<<channel.GetProcessId()<<endl;
    //   cout<<channel.GetName()<<endl;
    // }
   //2.通过channel控制进程
    ctrlProcess(channels,num);
    //3.回收管道和进程。a。关闭所有写端 ，b.回收子进程
    CleanUpChannel(channels);

   







    return 0;

}
